package cn.javaxc.mvcwork.util.contact;
import java.io.*;
import java.security.*;
import javax.net.ssl.*;


public class SSLMessage {

  private String url = null;
  private int port = -1;
  private String message = null;
  private String keystoreAlias = "aspcfs";
  private String keystoreLocation = null;
  private String keystorePassword = null;
  private StringBuffer response = null;


  
  public SSLMessage() {
  }


  
  public void setUrl(String tmp) {
    url = tmp;
  }


  
  public void setPort(int tmp) {
    port = tmp;
  }


  
  public void setKeystoreAlias(String tmp) {
    keystoreAlias = tmp;
  }


  
  public void setKeystoreLocation(String tmp) {
    this.keystoreLocation = tmp;
  }


  
  public void setKeystorePassword(String tmp) {
    this.keystorePassword = tmp;
  }


  
  public void setMessage(String tmp) {
    message = tmp;
  }


  
  public String getKeystoreLocation() {
    return keystoreLocation;
  }


  
  public String getKeystorePassword() {
    return keystorePassword;
  }


  
  public String getResponse() {
    return response.toString();
  }


  
  public int send() throws Exception {

    if (url == null || port < 0 || message == null) {
      return 1;
    }

    SSLSocket socket = null;

    try {
      SSLSocketFactory factory;
      if (keystoreLocation != null && keystorePassword != null) {
        //System.setProperty("java.protocol.handler.pkgs",
        //    "com.sun.net.ssl.internal.www.protocol");
        if (System.getProperty("DEBUG") != null) {
          System.out.println(
              "SSLMessage-> Keystore: " + keystoreLocation + ":" + keystorePassword);
        }

        char[] passphrase = keystorePassword.toCharArray();
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream(keystoreLocation), passphrase);

        if (keyStore.containsAlias(keystoreAlias) == false) {
          System.out.println(
              "Cannot locate identity: local private key not found.");
        }

        //Holds this peer's private key
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
            "SunX509");
        keyManagerFactory.init(keyStore, passphrase);
        KeyManager[] arKeyManager = keyManagerFactory.getKeyManagers();

        //Holds other peers' certificates
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
            "SunX509");
        trustManagerFactory.init(keyStore);
        TrustManager[] arTrustManager = trustManagerFactory.getTrustManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        sslContext.init(arKeyManager, arTrustManager, secureRandom);

        factory = sslContext.getSocketFactory();
      } else {
        factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
      }

      if (System.getProperty("DEBUG") != null) {
        System.out.println("SSLMessage-> Opening SSLSocket");
      }
      socket = (SSLSocket) factory.createSocket(url, port);

      //Untested
      //Get the certificate presented by the server
      /*
       *  SSLSession session = socket.getSession();
       *  X509Certificate cert;
       *  try { cert = (X509Certificate)session.getPeerCertificates()[0]; }
       *  catch(SSLPeerUnverifiedException e) { // If no or invalid certificate
       *  System.err.println(session.getPeerHost() +
       *  " did not present a valid certificate.");
       *  return;
       *  }
       */
      socket.setSoTimeout(30000);
      socket.startHandshake();
      if (System.getProperty("DEBUG") != null) {
        System.out.println("SSLMessage-> Sending Data");
      }
      PrintWriter out = new PrintWriter(
          new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
      out.println(message);
      out.println();
      out.flush();

      //Receive response - will timeout if server doesn't close connection
      if (System.getProperty("DEBUG") != null) {
        System.out.println("SSLMessage-> Receiving Data");
      }
      BufferedReader in = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null) {
        appendResponseLine(inputLine);
      }
      socket.close();
      return 0;
    } catch (java.net.SocketTimeoutException toe) {
      if (socket != null) {
        socket.close();
      }
      return 0;
    } catch (IOException io) {
      io.printStackTrace(System.out);
      return 1;
    }
  }


  
  private void appendResponseLine(String in) {
    if (response == null) {
      response = new StringBuffer();
    }
    response.append(in + System.getProperty("line.separator"));
  }
}
